﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Crawler
{
    public class AdvancedUri : System.Uri
    {
        public int Depth;
        SortedList<string, string> queryPartList;

        public AdvancedUri(string uriString)
            : base(uriString)
        {
            queryPartList = new SortedList<string, string>();

            if (!String.IsNullOrEmpty(base.Query))
            {
                string query = base.Query.Replace("&amp;", "&");
                string[] queryParts = query.Split('?','&');
                foreach (string part in queryParts)
                {
                    string[] sKeyValue = part.Split('=');
                    if (sKeyValue.Length > 0 && !String.IsNullOrEmpty(sKeyValue[0]))
                    {
                        string key = sKeyValue[0];
                        string value = String.Empty;
                        if (sKeyValue.Length > 1) value = sKeyValue[1];
                        queryPartList.Add(key, value);
                    }
                }
            }
        }

        public bool IsPartOf(AdvancedUri uri)
        {
            bool result = true;

            if (base.Scheme != uri.Scheme) result = false;
            if (!result || base.Host != uri.Host) result = false;
            if (!result || base.LocalPath != uri.LocalPath) result = false;

            int uriQueryPartsCount = uri.QueryPartsCount;
            for (int i = 0; i < queryPartList.Count && result && uriQueryPartsCount > 0; i++)
            {
                string key = queryPartList.Keys[i];
                string expectedValue = queryPartList.Values[i];
                string actualValue;
                result = uri.TryGetQueryValue(key, out actualValue);
                if (result && expectedValue != actualValue) result = false;
            }

            return result;
        }

        public bool Contains(AdvancedUri uri)
        {
            bool result = true;

            if (base.Scheme != uri.Scheme) result = false;
            if (!result || base.Host != uri.Host) result = false;
            if (!result || base.LocalPath != uri.LocalPath) result = false;

            for (int i = 0; i < uri.QueryPartsCount && result; i++)
            {
                string key = uri.GetQueryKey(i);

                string expectedValue;
                uri.TryGetQueryValue(key, out expectedValue);

                string actualValue;
                result = queryPartList.TryGetValue(key, out actualValue);
                if (result && expectedValue != actualValue) result = false;
            }

            return result;
        }

        public int QueryPartsCount
        {
            get
            {
                return queryPartList.Count;
            }
        }

        public string GetQueryKey(int index)
        {
            if (index < 0 || index >= queryPartList.Count) return String.Empty;
            return queryPartList.Keys[index];
        }

        public bool TryGetQueryValue(string key, out string value)
        {
            value = String.Empty;
            if (String.IsNullOrEmpty(key)) return false;
            return queryPartList.TryGetValue(key, out value);
        }
    }
}
